package com.graphe;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Segment implements INoeud, Serializable{
	private String id;
	private Point debut;
	private Point fin ;
	private String type;

	private List<String> croisements;
	private List<String> polygones;

	public Segment(){
		this.croisements = new ArrayList<String>();
		this.polygones = new ArrayList<String>();
	}
	public Segment(String id,Point deb, Point fin,List<String> segments,
			List<String> polygones){
		this.id = id;
		this.debut = deb;
		this.fin = fin;
		this.croisements = segments;
		this.polygones = polygones;
	}

	public Segment(String id,Point deb, Point fin){
		this.id = id;
		this.debut = deb;
		this.fin = fin;
		this.croisements = new ArrayList<String>();
		this.polygones =  new ArrayList<String>();
	}


	public void addPoint(Point p){
		if(this.debut == null)
			this.debut = p;
		else if(this.fin == null)
			this.fin = p;
	}

	public Point getDebut() {
		return debut;
	}

	public void addCroisement(Segment s){

		this.croisements.add(s.getId());
	}

	public void addPoly(Polygon p){
		this.polygones.add(p.getId());
	}

	public void addAllCroisement(List<Segment> ss){
		for(Segment s : ss)
			addCroisement(s);
	}

	public void addAllPoly(List<Polygon> ps){
		for(Polygon p : ps)
			addPoly(p);
	}

	public void setDebut(Point debut) {
		this.debut = debut;
	}

	public static List<String> segmentToId(List<Segment> segments){
		List<String> list = new ArrayList<String>();

		for(Segment s : segments)
			list.add(s.getId());

		return list;
	}

	public Point getFin() {
		return fin;
	}

	public void setFin(Point fin) {
		this.fin = fin;
	}

	public String toString(){
		StringBuffer st = new StringBuffer("\t<chemin id=\""+this.id+"\" type=\""+this.type+"\" >\n\n");

		System.out.println(this.id);
		if(type != null)
			System.out.println(this.type);
		
		// On affiche les points du segments
		st.append("\t\t"+this.debut.toString()+"\n");
		st.append("\t\t"+this.fin.toString()+"\n");

		// On affiche les chemins qui parte du segments
		for(String s : croisements)
			st.append("\n\t\t<chemin id=\""+ s +"\"/>");

		st.append("\n");
		// On affiche les batiments
		for(String b : polygones)
			st.append("\n\t\t<polygone id=\""+ b +"\"/>");

		st.append("\n");

		st.append("\n\t</chemin>");
		return st.toString();
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public List<String> getCroisements() {
		return croisements;
	}

	public void setCroisements(List<String> croisements) {
		this.croisements = croisements;
	}

	public List<String> getPolygones() {
		return polygones;
	}

	public void setPolygones(List<String> polygones) {
		this.polygones = polygones;
	}

	@Override
	public List<String> getChemin() {
		return croisements;
	}

	public float produitVectoriel(Segment s) {
		return (fin.getX() - debut.getX()) * (s.fin.getY() - s.debut.getY()) - (fin.getY() - debut.getY())
				* (s.fin.getX() - s.debut.getX());
	}

	public Point intersection(Segment s) {

		if (s.produitVectoriel(this) == 0){

			if((this.debut.getX() == s.debut.getX() && this.debut.getY() == s.debut.getY())
					|| (this.debut.getX() == s.fin.getX() && this.debut.getY() == s.fin.getY() )){
				return this.debut;
			}else if((this.fin.getX() == s.debut.getX() && this.fin.getY() == s.debut.getY() )
					||(this.fin.getX() == s.fin.getX() && this.fin.getY() == s.fin.getY())){
				return this.fin;
			}else{
				return null;
			}
		}

		Segment ss = new Segment("*",this.debut, s.getDebut());
		float a = (s.produitVectoriel(ss))
				/ s.produitVectoriel(this);

		if (a < 0 || a > 1)
			return null;
		else
			return new Point(debut.getX() + a * (fin.getX() - debut.getX()), debut.getY() + a
					* (fin.getY() - debut.getY()));
	}


	public static List<Segment> pointToList(List<Point>ps){
		List<Segment> segs = new ArrayList<Segment>();
		for(int i = 0 ; i < ps.size() - 1;i++){
			segs.add(new Segment("*",ps.get(i),ps.get(i+1)));
		}

		if(ps.size() > 2){
			segs.add(new Segment("*",ps.get(ps.size()-1),ps.get(0)));
		}
		return segs;
	}
	
	public String getType(){
		return this.type;
	}
	public void setType(String type2) {
		this.type = type2;
	}
	
	public float produitVectoriel(Point a, Point b, Point c) {
		return ((b.getX()-a.getX())*(c.getY()-a.getY()))-((b.getY()-a.getY())*(c.getX()-a.getX()));

	}

	public boolean dessous(Point p) {
		if(p.getY() > debut.getY() && p.getY()>fin.getY()){
			return false;
		}
		else if (p.getY() < debut.getY() && p.getY()<fin.getY()){
			System.out.println("dessous");

			return true;
		}
		else{
			if(debut.compareTo(fin) <= 0){
				//debut est en bas a gauche de fin
				//donc debut->fin,debut->p doit touner dnas le sens horaire, pVect <0
				if(produitVectoriel(debut, fin, p) <0){
					System.out.println("dessous");
					return true; //tournant dans le sens horaire
				}
				else{
					return false;
				}
			}
			else{
				//debut.compareTo(fin) >0
				//debut en haut a droite de fin
				//debut->fin, debut->p doit tourner �� gauche(anti-horaire)
				if(produitVectoriel(debut, fin, p) >0){
					System.out.println("dessous");

					return true; //tournant dans le sens anti-horaire
				}
				else{
					return false;
				}
			}
		}
	}

	public boolean dessus(Point p) {
		if(p.getY() > debut.getY() && p.getY()>fin.getY()){
			System.out.println("dessus");

			return true;
		}
		else if (p.getY() < debut.getY() && p.getY()<fin.getY()){
			return false;
		}
		else{
			if(debut.compareTo(fin) <= 0){
				//				debut est a gauche ou en dessous de fin
				if(produitVectoriel(debut, fin, p) >0){
					//					donc debut->fin , debut->p doit tourner trigo(anti-horaire)
					System.out.println("dessus");
					return true;
				}
				else{
					return false; 	
				} 
			}
			else{
				//debut.compareto(fin) >0 , donc debut est en haut a droite de fin
				//donc debut->fin, debut->p doit tourner anti-horaire
				if(produitVectoriel(debut, fin, p) <0){
					System.out.println("dessus");

					return true;
				}
				else{
					return false; 

				}	
			}
		}
	}

	
}
